package br.com.dao;

import java.util.List;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

import br.com.hibernate.HibernateUtil;

public class Dao {
	
	private static Dao instance;
	private Session sessao;
	private Transaction tx;
	
	private Dao(){
		
	}
	
	public static Dao getInstance(){
		if(instance == null)
			instance = new Dao();
		return instance;
	}
	
	public <T> Object buscarPorId(Class<T> clazz, Long id){
		try{
			sessao = HibernateUtil.getSession();
			Object object = sessao.get(clazz, id);
			return object;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public <T> Object buscarPorChaveUnicaLong(Class<T> clazz, Long longo, String coluna){
		try{
			sessao = HibernateUtil.getSession();
			Object object = sessao.createCriteria(clazz).add(Restrictions.eq(coluna, longo)).uniqueResult();
			return object;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public <T> Object buscarPorChaveUnicaString(Class<T> clazz, String stringi, String coluna){
		try{
			sessao = HibernateUtil.getSession();
			Object object = sessao.createCriteria(clazz).add(Restrictions.eq(coluna, stringi)).uniqueResult();
			return object;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public <T> List<?> buscarPorChaveEstrangeira(Class<T> clazz, Long chaveEstrangeira, String coluna){
		try{
			sessao = HibernateUtil.getSession();
			List<?> objects = sessao.createCriteria(clazz).add(Restrictions.eq(coluna, chaveEstrangeira)).list();
			return objects;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public <T> boolean salvarObjeto(T objeto){
		try{
			sessao = HibernateUtil.getSession();
			tx = sessao.beginTransaction();
			sessao.save(objeto);
			tx.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			sessao.close();
		}
	}
	
	public <T> boolean salvarOuAtualizarObjeto(T objeto){
		try{
			sessao = HibernateUtil.getSession();
			tx = sessao.beginTransaction();
			sessao.saveOrUpdate(objeto);
			tx.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			sessao.close();
		}
	}

	public <T> boolean atualizarObjeto(T objeto){
		try{
			sessao = HibernateUtil.getSession();
			sessao.setCacheMode(CacheMode.IGNORE);
			tx = sessao.beginTransaction();
			sessao.update(objeto);
			tx.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			sessao.close();
		}
	}
	
	public <T> boolean mesclarObjeto(T objeto){
		try{
			sessao = HibernateUtil.getSession();
			tx = sessao.beginTransaction();
			sessao.merge(objeto);
			tx.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			sessao.close();
		}
	}
	
	public <T> boolean deletarObjeto(T objeto){
		try{
			sessao = HibernateUtil.getSession();
			tx = sessao.beginTransaction();
			sessao.delete(objeto);
			tx.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			sessao.close();
		}
	}
	
	public List<?> listarObjetos(Class<?> classe){
		try{
			sessao = HibernateUtil.getSession();
			Criteria criteria = sessao.createCriteria(classe);
			return criteria.list();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
		
	public List<?> criarQuery(String query){
		try{
			sessao = HibernateUtil.getSession();
			Query select = sessao.createQuery(query);
			return select.list();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public Object criarQuery2(String query){
		try{
			sessao = HibernateUtil.getSession();
			Object obj = sessao.createQuery(query).uniqueResult();
			return obj;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public List<?> buscarPorLike(String coluna, String queryPart, Class clazz){
		try{
			sessao = HibernateUtil.getSession();
			List<?> objets = sessao.createCriteria(clazz).add(Restrictions.like(coluna, queryPart, MatchMode.ANYWHERE)).list();
			return objets;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}

	public <T> List<?> buscarPorValorDeColunaString(Class<T> clazz, String valor, String coluna){
		try{
			sessao = HibernateUtil.getSession();
			List<?> objects = sessao.createCriteria(clazz).add(Restrictions.eq(coluna, valor)).list();
			return objects;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public String buscarNecessidadeEspecial(Long id){
		try{
			sessao = HibernateUtil.getSession();
			String descricao = (String) sessao.createQuery("SELECT descricao FROM animal WHERE id="+id).uniqueResult();
			return descricao;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}

	public Object autenticarFuncionario(String cpf, String senha){
		try{
			sessao = HibernateUtil.getSession();
			Object obj = sessao.createQuery("FROM funcionario WHERE cpf='"+cpf+"' AND senha='"+senha+"'").uniqueResult();
			return obj;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public List<?> buscarPorNomeECategoriaComLike(String nome, String categoria){
		try{
			sessao = HibernateUtil.getSession();
			Query select = sessao.createQuery("FROM animal WHERE nome LIKE '%"+nome+"%' AND categoria = '"+categoria+"'");
			return select.list();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
	public List<?> buscarSemCategoriaAnimal(String nome, String categoria, int idade, String vacinado, String vermifugado, String especial, String raca, String sexo){
		try{
			sessao = HibernateUtil.getSession();
			Query select = sessao.createQuery("FROM animal WHERE nome LIKE '%"+nome+"%' AND categoria='"+categoria+"' AND idade="+idade+" AND vacinado='"+vacinado+"' AND vermifugado ='"+vermifugado+"' AND especial='"+especial+"' AND raca='"+raca+"' AND sexo='"+sexo+"'");
			return select.list();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			sessao.close();
		}
	}
	
}
